package main

import (
	"errors"
	"fmt"
	"io"
	"log"
	"net"
	"os"
	"os/signal"
	"time"
)

func chectError(err error) {
	if err != nil {
		fmt.Println(err)
	}
}

func copyNet(des, src net.Conn) {
	defer func() {
		fmt.Print("关闭socket")
		_ = des.Close()
		_ = src.Close()
	}()
	_, _ = io.Copy(des, src)
}

func handleConnection(conn net.Conn) {
	connEx, err := VerifySocket(conn)
	if err != nil {
		fmt.Println(err)
		conn.Close()
	} else {
		fmt.Println("开始准备传输数据")
		go copyNet(conn, connEx)
		go copyNet(connEx, conn)
	}

}

//验证socket5 是否通过
func VerifySocket(conn net.Conn) (net.Conn, error) {
	var vbuffer = make([]byte, 3)
	conn.Read(vbuffer)
	if vbuffer[0] == 5 && vbuffer[1] == 1 && vbuffer[2] == 0 {
		conn.Write([]byte{0x05, 0x00}) //Version 验证通过
		var buffer = make([]byte, 10)
		_, err := conn.Read(buffer)
		chectError(err)
		ip := fmt.Sprintf("%d.%d.%d.%d:%d", buffer[4], buffer[5], buffer[6], buffer[7], 256*int(buffer[8])+int(buffer[9]))

		connEx, err := net.DialTimeout("tcp", ip, 15*time.Second)
		if err != nil {
			conn.Write([]byte{0x05, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
			conn.Close()
			return nil, errors.New("连接远程服务器失败" + ip)

		} else {
			buffer[0] = 0x05
			buffer[1] = 0x00
			buffer[2] = 0x00
			buffer[3] = 0x01
			conn.Write(buffer)
			return connEx, nil
		}

	} else {
		return nil, errors.New("非socket5请求")
	}

}

func main() {

	stop_chan := make(chan os.Signal) // 接收系统中断信号
	signal.Notify(stop_chan, os.Interrupt)

	ln, err := net.Listen("tcp", ":8088")
	chectError(err)
	go func() {
		<-stop_chan
		ln.Close()
	}()

	chectError(err)
	fmt.Println("Socket5服务器监启动并监听端口8088...")

	for {
		conn, err := ln.Accept()
		if err != nil {
			chectError(err)
			break
		}
		fmt.Println("接收到连接..")
		go handleConnection(conn)
	}

}
